D:\git\skunkworks\herald-for-cpp\herald\include\herald\analysis\risk.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2021 Herald Project Contributors |
2 | | // SPDX-License-Identifier: Apache-2.0 |
3 | | // |
4 | | |
5 | | #ifndef HERALD_RISK_H |
6 | | #define HERALD_RISK_H |
7 | | |
8 | | #include <cmath> |
9 | | |
10 | | #include "aggregates.h" |
11 | | #include "ranges.h" |
12 | | #include "sampling.h" |
13 | | |
14 | | namespace herald { |
15 | | namespace analysis { |
16 | | namespace algorithms { |
17 | | namespace risk { |
18 | | |
19 | | using namespace herald::analysis::aggregates; |
20 | | |
21 | | /// A Basic sample but non scientific risk aggregation model. |
22 | | /// Similar in function to the Oxford Risk Model, but without its calibration values and scaling. |
23 | | /// NOT FOR PRODUCTION EPIDEMIOLOGICAL USE - SAMPLE ONLY!!! |
24 | | struct RiskAggregationBasic { |
25 | | static constexpr int runs = 1; |
26 | | |
27 | | RiskAggregationBasic(double timeScale,double distanceScale,double minimumDistanceClamp,double minimumRiskScoreAtClamp,double logScale = 3.3598856662 ) |
28 | | : run(1), timeScale(timeScale), distanceScale(distanceScale), minimumDistanceClamp(minimumDistanceClamp), |
29 | | minimumRiskScoreAtClamp(minimumRiskScoreAtClamp), logScale(logScale), nMinusOne(-1.0), n(-1.0), timeMinusOne(0), time(0), riskScore(0) |
30 | 1 | { |
31 | 1 | ; // no other set up |
32 | 1 | } |
33 | | ~RiskAggregationBasic() = default; |
34 | | |
35 | 11 | void beginRun(int thisRun) { // 1 indexed |
36 | 11 | run = thisRun; |
37 | 11 | if (1 == run) { |
38 | 11 | // clear run temporaries |
39 | 11 | nMinusOne = -1.0; |
40 | 11 | n = -1.0; |
41 | 11 | timeMinusOne = 0; |
42 | 11 | time = 0; |
43 | 11 | } |
44 | 11 | } |
45 | | |
46 | | template <typename SampleT> |
47 | 19 | void map(const herald::analysis::sampling::Sample<SampleT>& value) { |
48 | 19 | nMinusOne = n; |
49 | 19 | timeMinusOne = time; |
50 | 19 | n = value.value; |
51 | 19 | time = value.taken.secondsSinceUnixEpoch(); |
52 | 19 | } |
53 | | |
54 | 11 | double reduce() { |
55 | 11 | if (-1.0 != nMinusOne) { |
56 | 10 | // we have two values with which to calculate |
57 | 10 | // using nMinusOne and n, and calculate interim risk score addition |
58 | 10 | double dist = distanceScale * n; |
59 | 10 | double t = timeScale * (time - timeMinusOne); // seconds |
60 | 10 | |
61 | 10 | double riskSlice = minimumRiskScoreAtClamp; // assume < clamp distance |
62 | 10 | if (dist > minimumDistanceClamp) { |
63 | 9 | // otherwise, do the inverse log of distance to get the risk score |
64 | 9 | |
65 | 9 | // don't forget to clamp at risk score |
66 | 9 | riskSlice = minimumRiskScoreAtClamp - (logScale * std::log10(dist)); |
67 | 9 | if (riskSlice > minimumRiskScoreAtClamp) { |
68 | 0 | // possible as the passed in logScale could be a negative |
69 | 0 | riskSlice = minimumRiskScoreAtClamp; |
70 | 0 | } |
71 | 9 | if (riskSlice < 0.0) { |
72 | 7 | riskSlice = 0.0; // cannot have a negative slice |
73 | 7 | } |
74 | 9 | } |
75 | 10 | riskSlice *= t; |
76 | 10 | |
77 | 10 | // add it to the risk score |
78 | 10 | riskScore += riskSlice; |
79 | 10 | } |
80 | 11 | |
81 | 11 | // return current full risk score |
82 | 11 | return riskScore; |
83 | 11 | } |
84 | | |
85 | 0 | void reset() { |
86 | 0 | run = 1; |
87 | 0 | riskScore = 0.0; |
88 | 0 | nMinusOne = -1.0; |
89 | 0 | n = -1.0; |
90 | 0 | } |
91 | | |
92 | | private: |
93 | | int run; |
94 | | |
95 | | double timeScale; |
96 | | double distanceScale; |
97 | | double minimumDistanceClamp; |
98 | | double minimumRiskScoreAtClamp; |
99 | | double logScale; |
100 | | |
101 | | double nMinusOne; // distance of n-1 |
102 | | double n; // distance of n |
103 | | long timeMinusOne; // time of n-1 |
104 | | long time; // time of n |
105 | | |
106 | | double riskScore; |
107 | | }; |
108 | | |
109 | | } |
110 | | } |
111 | | } |
112 | | } |
113 | | |
114 | | #endif |